Feature: add partial pattern matching (partial=True) for callbacks#3765
Open
i-murray wants to merge 4 commits intoplotly:devfrom
Open
Feature: add partial pattern matching (partial=True) for callbacks#3765i-murray wants to merge 4 commits intoplotly:devfrom
i-murray wants to merge 4 commits intoplotly:devfrom
Conversation
Allow pattern-matching callbacks to match components whose IDs contain a superset of the pattern's keys. Opt-in per dependency via partial=True on Input, Output, and State. - Python: partial flag on DashDependency, subset-aware _id_matches() - JS/TS: addPartialPattern, partialIdMatch, resolvePartialDeps, updated getWatchedKeys, getCallbacksByInput, getCallbackByOutput, getUnfilteredLayoutCallbacks, resolveDeps, isMultiValued - Literal-only partial patterns are implicitly multi-valued - hasPartialPatterns guard for zero-cost when unused - 16 unit tests + 4 integration tests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Feature: Partial Pattern Matching (
partial=True) for CallbacksDescription
Dash's pattern-matching callbacks currently require the pattern and component IDs to have exactly the same set of keys. This means a pattern like
{"type": "btn"}will not match a component with ID{"type": "btn", "index": 1}— even though the component clearly has the key and value the pattern cares about.This PR adds an opt-in
partial=Trueflag onInput,Output, andStatethat relaxes the key-matching constraint: a pattern's keys only need to be a subset of the component's keys. Extra keys on the component are ignored.Closes #3764
Usage
This fires for any component whose ID contains
"type": "btn", regardless of other keys:{"type": "btn", "index": 1}{"type": "btn", "page": "home", "section": "main"}{"type": "btn", "index": 2, "tab": "first"}Works with wildcards:
Design choices
Input/Output/Stateindependently opts in, so partial and non-partial deps can coexist in the same callback.{"type": "btn"}withpartial=Truecan match multiple components, so the callback receives a list (same asALL). Patterns withMATCHstill resolve one-at-a-time.hasPartialPatternsboolean guard on the callback graph ensures apps withoutpartial=Truepay no additional overhead. All new loops are skipped entirely.Contributor Checklist
partialattribute toDashDependency,Input,Output,State(Python)_id_matches()for subset key matching whenpartial=Truepartialflag viato_dict()and propagate throughinsert_callback()addPartialPattern()andpartialIdMatch()to frontend (dependencies.js)computeGraphs()to detect partial flags and sethasPartialPatternsgetWatchedKeys(),getCallbackByOutput(),getUnfilteredLayoutCallbacks()with partial pattern loopsresolvePartialDeps()and updategetCallbacksByInput()independencies_ts.tsisMultiValued()for implicit multi-valued partial patternsrequestedCallbacks.tstype compatibility for updatedisMultiValuedsignaturehasPartialPatternsguard to all new loops for zero-cost when unusedtests/unit/test_partial_matching.py— subset matching, wildcards, serialization, bidirectional checks, negative casestests/integration/callbacks/test_partial_wildcards.py— basic partial match, ALL collection, literal filtering, mixed key setsOptionals
CHANGELOG.mdPerformance
Partial matching requires cross-keyStr searches in several hot-path functions that were previously$O(1)$ hash lookups:
getWatchedKeys()getCallbacksByInput()getCallbackByOutput()getUnfilteredLayoutCallbacks()Where$K$ = number of distinct keyStr entries in the pattern index, $p$ = number of keys in the pattern (typically 1–5), and $N$ = number of components in a layout chunk.
hasPartialPatternsguardTo ensure zero cost for apps that don't use$O(D)$ time (where $D$ = total dependencies). Every new loop is guarded:
partial=True,computeGraphs()sets ahasPartialPatternsboolean on the graph in